package cn.foolishbird.crow.core.util;

/**
 * 注意long溢出
 * @author  luohongtu
 * @date: 2023/4/7
 */
public enum MemoryUnit {


    BYTE {
        @Override
        public long toByte(long source) {
            return source;
        }

        @Override
        public long toKB(long source) {
            return  source/(K/B);
        }

        @Override
        public long toMB(long source) {
            return  source/(M/B);
        }

        @Override
        public long toGB(long source) {
            return  source/(G/B);
        }

        @Override
        public long toTB(long source) {
            return  source/(T/B);
        }

        @Override
        public long toPB(long source) {
            return  source/(P/B);
        }

        @Override
        public long convert(long source, MemoryUnit sourceUnit) {
            return sourceUnit.toByte(source);
        }
    },
    KB {
        @Override
        public long toByte(long source) {
            return x(source, K/B, MAX/(K/B));
        }

        @Override
        public long toKB(long source) {
            return  source;
        }

        @Override
        public long toMB(long source) {
            return  source/(M/K);
        }

        @Override
        public long toGB(long source) {
            return  source/(G/K);
        }

        @Override
        public long toTB(long source) {
            return  source/(T/K);
        }

        @Override
        public long toPB(long source) {
            return  source/(P/K);
        }

        @Override
        public long convert(long source, MemoryUnit sourceUnit) {
            return sourceUnit.toKB(source);
        }
    },

    MB {
        @Override
        public long toByte(long source) {
            return x(source, M/B, MAX/(M/B));
        }

        @Override
        public long toKB(long source) {
            return x(source, M/K, MAX/(M/K));
        }

        @Override
        public long toMB(long source) {
            return  source;
        }

        @Override
        public long toGB(long source) {
            return  source/(G/M);
        }

        @Override
        public long toTB(long source) {
            return  source/(T/M);
        }

        @Override
        public long toPB(long source) {
            return  source/(P/M);
        }

        @Override
        public long convert(long source, MemoryUnit sourceUnit) {
            return sourceUnit.toMB(source);
        }
    },

    GB {
        @Override
        public long toByte(long source) {
            return x(source, G/B, MAX/(G/B));
        }

        @Override
        public long toKB(long source) {
            return x(source, G/K, MAX/(G/K));
        }

        @Override
        public long toMB(long source) {
            return x(source, G/M, MAX/(G/M));
        }

        @Override
        public long toGB(long source) {
            return  source;
        }

        @Override
        public long toTB(long source) {
            return  source/(T/G);
        }

        @Override
        public long toPB(long source) {
            return  source/(P/G);
        }

        @Override
        public long convert(long source, MemoryUnit sourceUnit) {
            return sourceUnit.toGB(source);
        }
    },

    TB {
        @Override
        public long toByte(long source) {
            return x(source, T/B, MAX/(T/B));
        }

        @Override
        public long toKB(long source) {
            return x(source, T/K, MAX/(T/K));
        }

        @Override
        public long toMB(long source) {
            return x(source, T/M, MAX/(T/M));
        }

        @Override
        public long toGB(long source) {
            return x(source, T/G, MAX/(T/G));
        }

        @Override
        public long toTB(long source) {
            return  source;
        }

        @Override
        public long toPB(long source) {
            return  source/(P/T);
        }

        @Override
        public long convert(long source, MemoryUnit sourceUnit) {
            return sourceUnit.toTB(source);
        }
    },

    PB {
        @Override
        public long toByte(long source) {
            return x(source, P/B, MAX/(P/B));
        }

        @Override
        public long toKB(long source) {
            return x(source, P/K, MAX/(P/K));
        }

        @Override
        public long toMB(long source) {
            return x(source, P/M, MAX/(P/M));
        }

        @Override
        public long toGB(long source) {
            return x(source, P/G, MAX/(P/G));
        }

        @Override
        public long toTB(long source) {
            return x(source, P/T, MAX/(P/T));
        }

        @Override
        public long toPB(long source) {
            return  source;
        }

        @Override
        public long convert(long source, MemoryUnit sourceUnit) {
            return sourceUnit.toPB(source);
        }
    }

    ;



    /**
     * 1byte = 8bit
     */
    private static final long B = 1L;

    /**
     * 1KB
     */
    private static final long K = B * 1024;

    /**
     * 1MB
     */
    private static final long M = K * 1024;

    /**
     * 1GB
     */
    private static final long G = M * 1024;

    /**
     * 1TB
     */
    private static final long T = G * 1024;

    /**
     * PB
     */
    private static final long P = T * 1024;

    /**
     * 最大值
     */
    private static final long MAX = Long.MAX_VALUE;

    /**
     *
     * @param d
     * @param m
     * @param over
     * @return
     */
    static long x(long d, long m, long over) {
        if (d > over) {
            return Long.MAX_VALUE;
        }
        if (d < -over) {
            return Long.MIN_VALUE;
        }
        return d * m;
    }

    public long toByte(long source) {
        throw new AbstractMethodError();
    }

    public long toKB(long source) {
        throw new AbstractMethodError();
    }

    public long toMB(long source) {
        throw new AbstractMethodError();
    }

    public long toGB(long source) {
        throw new AbstractMethodError();
    }

    public long toTB(long source) {
        throw new AbstractMethodError();
    }

    /**
     * toPB
     * @param source
     * @return
     */
    public long toPB(long source) {
        throw new AbstractMethodError();
    }

    /**
     * 转换类型
     *
     * @param source
     * @param sourceUnit
     * @return
     */
    public long convert(long source, MemoryUnit sourceUnit) {
        throw new AbstractMethodError();
    }

}
